class Vue{
  constructor(obj_instance) {
    this.$data = obj_instance.data
    Observer(this.$data) // 监听data数据
    // 将数据更新到DOM上面
    Compile(obj_instance.el,this)
  }
}

// 数据劫持
function Observer(data_instance) {
  // console.log(data_instance)
  Object.keys(data_instance).forEach(key => {
    let value = data_instance[key]
    // 递归
    if (value instanceof Object) { 
      Observer(value)
    } else { 
       Object.defineProperty(data_instance, key, {
      enumerable: true, // 可枚举
      configurable: true,
      get() { 
        // console.log('get触发了')  //get每次回改变原来的值
        return value
        // return data_instance[key]  // 超限
      }, //访问的时候触发
      set(newValue) {
        value=newValue 
        // console.log('set触发了')
        Observer(newValue)
       } ,//接受数值的时候触发
    })
    } 
  })
}

function Compile(element, vm) {
  // 创建虚拟的Dom(内存中)
  vm.$el = document.querySelector(element) // vue中的el存放的是获取的DOM的元素
  //使用文档碎片进行集中的管理数据
  const fragment = document.createDocumentFragment()

  // console.log(vm.$el.childNodes) // 所有的子节点
  // console.log(vm.$el)
  // console.log(vm.$el.firstChild) // dom的首个子节点
  // fragment.append(vm.$el.firstChild)
  // console.log(vm.$el.childNodes) // childNodes 和cchildren 是有区别的

  while (child = vm.$el.firstChild) {
    fragment.append(child) // 每当文档碎片增加一个，实际的Dom就减少一个节点
  }
  fragment_compile(fragment)
  // console.log(fragment)
  // console.log('--------------------')
  // console.log(fragment.childNodes)
  // console.log('-----------------------')

  function fragment_compile(node) {
    // forEach 不会空数组进行遍历
    const regExp = /{{\s*(\S+)\s*}}/;  // 想到了函数的柯里化
    if (node.data && (node.data + '').trim()) {
      const key = regExp.exec((node.data + '').trim())
      if (key) {
        const re = key[1].split('.').reduce((prev, item) => prev[item], vm.$data)
        // console.log(typeof node) // object
        node.nodeValue=node.nodeValue.replace(regExp,re)
        // node.replace(regExp,re)
      }
    }
    node.childNodes.forEach(item => {
      fragment_compile(item)
    })
  }
  vm.$el.appendChild(fragment)
}